package com.wall.springbootinit.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.net.NetUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.extra.mail.MailUtil;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wall.springbootinit.common.ErrorCode;
import com.wall.springbootinit.exception.BusinessException;

import com.wall.springbootinit.model.dto.user.RetrievePasswordDTO;
import com.wall.springbootinit.model.dto.user.UserLoginDTO;
import com.wall.springbootinit.model.entity.User;

import com.wall.springbootinit.model.vo.EmailCaptchaVo;
import com.wall.springbootinit.model.vo.UserVo;
import com.wall.springbootinit.service.UserService;
import com.wall.springbootinit.mapper.UserMapper;
import com.wall.springbootinit.utils.NetUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

/**
 * @author 33932
 * @description 针对表【sys_user(用户表)】的数据库操作Service实现
 * @createDate 2024-05-19 15:27:39
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public String login(UserLoginDTO userLoginDTO) {
        Integer loginType = userLoginDTO.getLoginType();
        String userAccount = userLoginDTO.getUserAccount();
        String email = userLoginDTO.getEmail();
        String emailCodeId = userLoginDTO.getEmailCodeId();
        String userPassword = userLoginDTO.getUserPassword();
        String captcha = userLoginDTO.getCaptcha();
        if (loginType == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 如果是账号密码
        if (loginType == 0) {
            // 校验为空
            if (StringUtils.isAnyBlank(userAccount, userPassword)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR);
            }
            // 密码加密
            String md5Hex = DigestUtil.md5Hex(userPassword);
            // 查询用户
            User queryUser = lambdaQuery().eq(User::getUserAccount, userAccount)
                    .eq(User::getUserPassword, md5Hex)
                    .one();
            if (queryUser == null){
                throw new BusinessException(ErrorCode.USER_NOT_FOUNT);
            }
            // 登录
            StpUtil.login(queryUser.getBusinessId());
            return StpUtil.getTokenValue();
        }else if (loginType == 1){
            // 校验为空
            if (StringUtils.isAnyBlank(email, emailCodeId, captcha)){
                throw new BusinessException(ErrorCode.PARAMS_ERROR);
            }
            // 校验验证码
            checkCaptcha(emailCodeId, captcha);
            // 查询用户
            User user = lambdaQuery().eq(User::getEmail, email).one();
            if (user == null){
                throw new BusinessException(ErrorCode.USER_NOT_FOUNT);
            }
            // 登录
            StpUtil.login(user.getBusinessId());
            return StpUtil.getTokenValue();
        }
        throw new BusinessException(ErrorCode.OPERATION_ERROR);
    }

    /**
     * 校验验证码
     * @param emailCodeId 验证码存储id
     * @param captcha 验证码
     */
    private void checkCaptcha(String emailCodeId, String captcha) {
        // 构建redisKey
        String redisKey = "captcha:" + emailCodeId;
        // 判断redisKey是否存在
        if (Boolean.FALSE.equals(redisTemplate.hasKey(redisKey))){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        // 获取redisKey的值
        String redisValue = redisTemplate.opsForValue().get(redisKey);
        // 校验指
        if (!Objects.equals(captcha, redisValue)){
            // 销毁key
            redisTemplate.delete(redisKey);
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"验证码校验失败！");
        }
    }

    /**
     * 获取验证码
     * @param email 邮箱
     * @return 验证码
     */
    @Override
    public EmailCaptchaVo getCaptcha(String email, HttpServletRequest request) {
        // 生成验证码
        int code = ThreadLocalRandom.current().nextInt(100000, 1000000);
        // 生成验证码key
        String uuidCode = UUID.randomUUID().toString();
//        // 获取ip
//        String ipAddress = NetUtils.getIpAddress(request);
        // 构建rediskey
        String redisKey = "captcha:" + uuidCode;
//        // 构建key
//        String addKey = "address:" + ipAddress;
//        if (Boolean.TRUE.equals(redisTemplate.hasKey(addKey))){
//            throw new BusinessException(ErrorCode.OPERATION_ERROR,"验证码发送过于频繁");
//        }
//        redisTemplate.opsForValue().set(addKey, "1", 3, TimeUnit.MINUTES);
        // 设置redisKey的值
        redisTemplate.opsForValue().set(redisKey, String.valueOf(code), 300, TimeUnit.SECONDS);
        // 发送邮件
        MailUtil.send(email , "测试", "验证码为" + code + "，请于5分钟内完成验证。", false);
        // 封装返回值
        EmailCaptchaVo emailCaptchaVo = new EmailCaptchaVo();
        emailCaptchaVo.setUuid(uuidCode);
        return emailCaptchaVo;
    }

    /**
     * 重置密码
     * @param retrievePasswordDTO 重置密码参数
     * @return 重置密码结果
     */
    @Override
    public boolean retrievePassword(RetrievePasswordDTO retrievePasswordDTO) {
        String userPassword = retrievePasswordDTO.getUserPassword();
        String encryptPassword = retrievePasswordDTO.getEncryptPassword();
        if (StringUtils.isAnyBlank(userPassword, encryptPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (!Objects.equals(userPassword, encryptPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"两次密码不同");
        }
        // 获取登录id
        Long loginId = StpUtil.getLoginIdAsLong();
        User user = lambdaQuery().eq(User::getBusinessId, loginId).one();
        if (user == null){
            throw new BusinessException(ErrorCode.USER_NOT_FOUNT);
        }
        user.setUserPassword(DigestUtil.md5Hex(userPassword));
        int i = userMapper.updateById(user);
        if (i == 0){
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }
        // 踢下线
        StpUtil.logout();
        return true;
    }

    /**
     * 获取当前用户
     * @param loginId 登录id
     * @return 用户信息
     */
    @Override
    public UserVo getCurrentUser(Object loginId) {
        long id;
        try {
            id = Long.parseLong(loginId.toString());
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User user = userMapper.selectById(id);
        if (user == null){
            throw new BusinessException(ErrorCode.USER_NOT_FOUNT);
        }
        return BeanUtil.toBean(user, UserVo.class);
    }
}




